/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package merlion.common.session.stateless;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import merlion.common.entity.Message;
import merlion.common.entity.Staff;
import merlion.common.entity.SystemUserAccount;
import merlion.common.util.Consts;

/**
 *
 * @author Zhang Ying
 */
@Stateless
public class InternalMessageSession implements InternalMessageSessionLocal {

    @PersistenceContext
    private EntityManager entityManager;

    @Override
    public Collection<SystemUserAccount> getAllSystemUserAccounts() {
        Query query = entityManager.createQuery("SELECT sua FROM SystemUserAccount sua");
        return (List<SystemUserAccount>) query.getResultList();
    }

    @Override
    public boolean sendMessage(Message newMessage, SystemUserAccount sender, SystemUserAccount[] receivers) {
        try {
            // the passed in message is set before passed in
            // need to update the sender and receiver's msg list
            boolean merged = false;
            for (SystemUserAccount s : receivers) {
                Message newRcvMsg = new Message();
                newRcvMsg.setContent(newMessage.getContent());
                newRcvMsg.setSubject(newMessage.getSubject());
                newRcvMsg.setSenderAccId(newMessage.getSenderAccId());
                newRcvMsg.setReceiverAccIds(newMessage.getReceiverAccIds());
                newRcvMsg.setCreatedTime(newMessage.getCreatedTime());
                newRcvMsg.setHaveRead(Consts.MSG_HAVE_NOT_READ);
                newRcvMsg.setType(Consts.MSG_TYPE_RECEIVED);
                if (s.getId().equals(sender.getId())) {
                    merged = true;
                    s.getMessages().add(newRcvMsg);
                    s.getMessages().add(newMessage);
                } else {
                    s.getMessages().add(newRcvMsg);
                }
                entityManager.merge(s);
            }
            if (merged == false) {
                sender.getMessages().add(newMessage);
                entityManager.merge(sender);
            }
            return true;
        } catch (Exception ex) {
            return false;
        }
    }

    @Override
    public Collection<Message> getAllMySentMessage(Long staffId) {
        Staff s = entityManager.find(Staff.class, staffId);
        Collection<Message> msgs = s.getSystemUserAccount().getMessages();
        Collection<Message> result = new ArrayList<Message>();
        for (Message msg : msgs) {
            if (msg.getType().equals(Consts.MSG_TYPE_SENT)) {
                result.add(msg);
            }
        }
        return result;
    }

    @Override
    public Staff getSenderStaff(Long accId) {
        SystemUserAccount sua = entityManager.find(SystemUserAccount.class, accId);
        return sua.getStaff();
    }

    @Override
    public Message getMessage(Long id) {
        return entityManager.find(Message.class, id);
    }

    @Override
    public boolean deleteMessage(Long id, Long staffId) {
        Message msg = entityManager.find(Message.class, id);
        Staff s = entityManager.find(Staff.class, staffId);
        try {
            s.getSystemUserAccount().getMessages().remove(msg);
            entityManager.merge(s);
            entityManager.remove(msg);
            return true;
        } catch (Exception ex) {
            return false;
        }
    }

    @Override
    public boolean deleteManyMessages(Message[] selectedDeletion, Long staffId) {
        try {
            int i = 0;
            Message msg;
            Staff s = entityManager.find(Staff.class, staffId);
            Collection msgs = Arrays.asList(selectedDeletion);
            s.getSystemUserAccount().getMessages().removeAll(msgs);
            entityManager.merge(s);
            while (i < selectedDeletion.length){
                msg = entityManager.find(Message.class, selectedDeletion[i].getId());
                entityManager.remove(msg);
                i++;
            }
            return true;
        } catch (Exception ex) {
            ex.printStackTrace();
            return false;
        }
    }

    @Override
    public Staff getUpdatedStaff(Long id) {
        return entityManager.find(Staff.class, id);
    }

    @Override
    public Collection<Message> getAllMyReceivedMessages(Long staffId) {
        Staff s = entityManager.find(Staff.class, staffId);
        Collection<Message> msgs = s.getSystemUserAccount().getMessages();
        Collection<Message> result = new ArrayList<Message>();
        for (Message msg : msgs) {
            if (msg.getType().equals(Consts.MSG_TYPE_RECEIVED)) {
                result.add(msg);
            }
        }
        return result;
    }

    @Override
    public Message updateNGetReadMsg(Long id) {
        try{
            Message originalMsg = entityManager.find(Message.class, id);
            originalMsg.setHaveRead(Consts.MSG_HAVE_READ);
            entityManager.merge(originalMsg);
            return originalMsg;
        }catch(Exception ex){
            ex.printStackTrace();
            return null;
        }
    }

    @Override
    public boolean replyMessage(Message repliedMsg) {
        try {
            // the passed in message is set before passed in
            // need to update the sender and receiver's msg list
            boolean merged = false;
            for (Long receiverId : repliedMsg.getReceiverAccIds()){
                SystemUserAccount s = entityManager.find(SystemUserAccount.class, receiverId);
                Message newMsg = new Message();
                newMsg.setSubject(repliedMsg.getSubject());
                newMsg.setContent(repliedMsg.getContent());
                newMsg.setSenderAccId(repliedMsg.getSenderAccId());
                newMsg.setReceiverAccIds(repliedMsg.getReceiverAccIds());
                newMsg.setCreatedTime(repliedMsg.getCreatedTime());
                newMsg.setHaveRead(Consts.MSG_HAVE_NOT_READ);
                newMsg.setType(Consts.MSG_TYPE_RECEIVED);
                if (receiverId.equals(repliedMsg.getSenderAccId())){
                    merged = true;
                    s.getMessages().add(newMsg);
                    s.getMessages().add(repliedMsg);
                }else {
                    s.getMessages().add(newMsg);
                }
                entityManager.merge(s);
            }
            if (merged == false) {
                SystemUserAccount sender = entityManager.find(SystemUserAccount.class, repliedMsg.getSenderAccId());
                sender.getMessages().add(repliedMsg);
                entityManager.merge(sender);
            }
            return true;
        } catch (Exception ex) {
            return false;
        }
    }

    @Override
    public Collection<Message> getNewRcvedUnreadMsg(Long accId) {
        SystemUserAccount sua = entityManager.find(SystemUserAccount.class, accId);
        List<Message> lists =(List<Message>) sua.getMessages();
        Collection<Message> result = new ArrayList<Message>();
        for (int i = lists.size()-1; i>=0; i--){
            Message msg = lists.get(i);
            if (msg.getHaveRead().equals(Consts.MSG_HAVE_NOT_READ) && msg.getType().equals(Consts.MSG_TYPE_RECEIVED)){
                result.add(msg);
            }
        }
        return result;
    }
}
